#include<stdio.h>
#include<stdlib.h>
#include<at89c51ed2.h>
#include <mcs51reg.h>
#include<malloc.h>
#include<ctype.h>

#define HEAP_SIZE 1600	//heap size of 1600
unsigned char xdata heap[HEAP_SIZE];


void _sdcc_external_startup() {
	AUXR|=0x0C;	//XRAM 1024 bytes activated
	TMOD|=0x20;		//Mode 2
	TH1=0xFD;		// Timer Value 253
	SCON = 0x50; // SCON: mode 1, 8-bit UART, enable rcvr
	PCON|=0x80;		// double baud rate to 19200
	TR1 = 1; // TR1: timer 1 run
	TI = 1;	//set TI flag for putchar sequence
	RI = 0;	
}


//Virtual Debug Port Operation

#define DEBUG

#ifdef DEBUG
#define DEBUGPORT(x) dataout(x); // generates a MOVX 0FFFFh,x where x is an 8-bit value
#else
#define DEBUGPORT(x)
// empty statement, nothing passed on from the preprocessor to the compiler
#endif


//function definitions referenced in main()
void scanF(char* val,int size);
int isAllDigit(char * val);
char * emptyBuffer(char * val,char * src);
void upperLower(char *val,int n);
void printHex(char *val);
void putstr (char *s); 
void enterWait();
void clrScr();
void newLine();
void calStats(char *val);
void dataout(int val); //debug port function


/*Segmentation Error means malloc needs to be used!*/
/*check if all loops have i++,!*/	


void main(void) 
{
	xdata char * buffer0;  // pointers
	xdata char * buffer1;
	xdata char * buffer2;
	unsigned char * Size;// stores the buffer size value in char form
	unsigned int bufferSize; //stores the buffer size in int form, as a single number
	char *addr;
	int i; //just a counter
	int storageChar;
	int totalChar;
	char t;
	int space;

	
	
	
	//initialisation functions
	init_dynamic_memory((MEMHEADER xdata *)heap, HEAP_SIZE); 
	/****************************************************************************************************************/
	//user buffer size input
	userBuffer:clrScr();  //clears any previous data on screen
	newLine(); //horizontal line on screen
	printf_tiny("Enter buffer size:");					//user input for buffer size
	
	Size=(char *)malloc(4);  //allocate 4 bytes for char array 
	scanF(Size,4); //gets the buffer size value in char form

	
	if(isAllDigit(Size)!=0){  //incase user has entered non-digit values
		printf_tiny("\r\nPlease enter number only 0-9");
		enterWait();
		goto userBuffer;
	}
	
	bufferSize=atoi(Size); //convert char array Size to a single integer value
	//dataout(0x01);
	free(Size);		//deallocating space used for Size
	
	if (bufferSize<24||bufferSize>1600){
		
		printf_tiny("\r\nPlease enter buffer size between 24 to 1600 bytes");
		enterWait();
		goto userBuffer;
	}
	
	if((bufferSize%8)!=0){  //check if buffer size is divisible by 8
		printf_tiny("\r\nPlease enter size that is divisible by 8");
		enterWait();
		goto userBuffer;
	}
	
	
	
	
	//have user defined buffer value with all error checking
	/****************************************************************************************************************/
	//buffer allocation
	
	if ((buffer0 = malloc(sizeof(char)*bufferSize)) == 0)
	{  //allocate buffer0
		printf_tiny("\n\r\t\t\tSorry,Malloc buffer0 failed");
		enterWait();
		goto userBuffer;
	}
				
	if ((buffer1 = malloc(sizeof(char)*(bufferSize/8))) == 0)         //allocate buffer1
	{
			printf_tiny("\n\r\t\t\tMalloc buffer1 failed");
			free (buffer0);  // if buffer1 malloc fails, free buffer 0
			enterWait();
			goto userBuffer;
	}	
			
	if ((buffer2 = malloc(sizeof(char)*(bufferSize/8))) == 0)         //allocate buffer1
	{
			printf_tiny("\n\r\t\t\tMalloc buffer2 failed\n\r");
			free(buffer0);  // if buffer1 malloc fails, free buffer 0
			free(buffer1);  // if buffer2 malloc fails, free buffer 0,1
			enterWait();
			goto userBuffer;
	}
		
	
	
	
	printf_tiny("\r\nBuffer Allocation Succesfull!\n\n");
	printf_tiny("\rBuffer No.\t\tStarting Address\t\tBuffer Size\r\n");
	newLine();
	printf("\t0\t\t%p\t\t\t%d\r\n",buffer0,bufferSize);
	printf("\t1\t\t%p\t\t\t%d\r\n",buffer1,(bufferSize/8));
	printf("\t2\t\t%p\t\t\t%d\r\n",buffer2,(bufferSize/8));
	newLine();
	
	//buffer allocation done!
	/*****************************************************************************************************************/
	
	addr=buffer0;   //to keep buffer0 ie base address value intact				
	
	
	//character entry part
	
	userEntry:printf_tiny("\n\rEnter Characters Now:\n\r");
	newLine();
	i=1; //used to count to buffer size
	storageChar=0;
	totalChar=0;
	space=0;
	
	while(1){
		
			t = getchar();    //tale user character input
			
			
			putchar(t); //echo characters back
			printf_tiny("\t");
			space++;
			if (space==10){
							printf_tiny("\n\r");
							space=0;
			}
			
						
			
			switch(t)
			{
				case '?':clrScr();
						 printf_tiny("\t\t\tWelcome to the data display screen\r\n");	//? for special operations
						 newLine();
						 printf("\rTotal Number of Characters Received:%d		\n",totalChar);
						 printf("\rNumber of Storage Characters Received:%d	\n",storageChar);
						 printf("\rStarting Address of Buffer 0:%p		\n",buffer0);
						 printf("\rAllocated Size of Buffer 0: %d			\n",bufferSize);
						 printf("\rStarting Address of Buffer 1:%p		\n",buffer1);
						 printf("\rAllocated Size of Buffer 1: %d			\n",(bufferSize/8));
						 printf("\rStarting Address of Buffer 2:%p		\n",buffer2);
						 printf("\rAllocated Size of Buffer 2: %d			\r\n",(bufferSize/8));
						 newLine();
						 printf_tiny("Buffer Statistics (Value : Number of Occurences)\r\n");
						 newLine();
						 calStats(buffer0); //latest entry since last validation!
						 newLine();
						 printf_tiny("Buffer Contents:\r\n");
						 newLine();
						 printf_tiny("\r\n");
						 //*addr='\n';  //append a NULL character at end, to demarcate end of char string
						 addr=emptyBuffer(addr,buffer0); //will print all received alpahnumeric char, and empty buffer()
						 i=1;//restart the buffer size counter
						 storageChar=0; //restart number of storage char received
					 	 totalChar=0; //restart number of total char received
					 	 printf_tiny("\r\nBuffer Emptied,Restarting Buffer Storage");
					 	 goto userEntry;
						 break;
				
			   case ']' :upperLower(buffer0,1);	  //call to upperLower
					     printf("\n\r\t\t\tConverted all lower characters to Upper");
					     break;
					     
			   case '[' :upperLower(buffer0,0);	//call to upperLower
					     printf("\n\r\t\tConverted all Upper characters to Lower");
					     break;
			   case '=': printf_tiny("\r\n");
			   			 printHex(buffer0);
			   			 break; 
			   
			
								 
				
			     default:
						if(i<=bufferSize){ //when buffer is not full
							totalChar++; //count the total number of all characters received
							if(isalnum(t)!=0){ //if alphanumeric that is a-z, A-Z, 0-9 received
							*addr=t;  //may need to use malloc for addr if there are problems!	
							addr++; //point to next consecutive location
							*addr='\n';
							
							i++; //increment counter only if alphanumeric char is received	
							storageChar++;	
							break; //put here to avoid displaying last character as soon as buffer is full
							}
						}
						if(i>bufferSize){ //when buffer becomes full
							printf("\r\n Warning Buffer Full!, No new character will be stored.Press ? to empty buffer\r\n");
							//printf("%c",t);				
						}
			}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
